#pragma once

#include "mat4.h"
#include "vec4.h"
#include "SmartPtr.h"
#include "Cvars.h"

class Camera;
typedef SmartPtr<Camera> CameraPtr;

class IRenderer;
typedef SmartPtr<IRenderer> RendererPtr;

class Camera
{
public:
	enum eType
	{
		ORTHOGRAPHIC,
		PERSPECTTIVE_NORMAL,
		PERSPECTTIVE_FOV,
	};

	enum eTransfromType
	{
		WORLD_FRAME,
		VIEW_FRAME,
	};

public:
	Camera(const Vec3& eye = INITIAL_EYE, const Vec3& at = INITIAL_AT, const Vec3& up = INITIAL_UP);

	void update();

	void lookAt(const Vec3& eye, const Vec3& at, const Vec3& up);

	void move(float x = 0.0f, float y = 0.0f, float z = 0.0f);

	void rotate(float x = 0.0f, float y = 0.0f, float z = 0.0f);

	Mat4 getTransform();

	Mat4 getProjection();

	Vec3 getPosition();

	void getBounds(float *left, float *right, float *bottom, float *top, float *near, float *far);

	void drawMark(RendererPtr render);

private:
	Mat4 ortho(float left, float right, float bottom, float top, float near, float far);

	Mat4 frustum(float left, float right, float bottom, float top, float near, float far);

	Mat4 perspective(float fovy, float aspect, float near, float far);

private:
	static Vec3 INITIAL_EYE;
	static Vec3 INITIAL_AT;
	static Vec3 INITIAL_UP;

	Mat4 _translations;
	Mat4 _rotations;

	Mat4 _transform;

	CvarPtr _type;
	CvarPtr _transformType;

	CvarPtr _left;
	CvarPtr _right;
	CvarPtr _bottom;
	CvarPtr _top;
	CvarPtr _near;
	CvarPtr _far;
	CvarPtr _fovy;
	CvarPtr _zoom;
	CvarPtr _width;
	CvarPtr _height;

	CvarPtr _mark;
	CvarPtr _markSize;
	CvarPtr _markColor;
};